package com.icesoft.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.icesoft.framework.core.cache.RedisCacheManager;
import com.icesoft.framework.core.config.Cons;
import com.icesoft.framework.core.controller.BaseCrudRestController;
import com.icesoft.framework.core.exception.BusinessException;
import com.icesoft.framework.core.vo.JsonResult;
import com.icesoft.framework.core.vo.Pagination;
import com.icesoft.system.dto.AccountDTO;
import com.icesoft.system.dto.BindEmailDTO;
import com.icesoft.system.dto.BindPhoneDTO;
import com.icesoft.system.dto.ChangPasswordDTO;
import com.icesoft.system.entity.Account;
import com.icesoft.system.entity.User;
import com.icesoft.system.permission.OperationCons;
import com.icesoft.system.permission.annotation.BindPermission;
import com.icesoft.system.service.impl.AccountServiceImpl;
import com.icesoft.system.service.impl.UserServiceImpl;
import com.icesoft.system.types.AuthTypeDictionary;
import com.icesoft.system.types.SystemSettingTypeDictionary;
import com.icesoft.system.util.PasswordUtil;
import com.icesoft.system.vo.AccountVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * 账号Controller
 *
 * @author ${author}
 * @date 230326
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@BindPermission(name = "账号管理")
@RequestMapping("/system/account")
public class AccountController extends BaseCrudRestController<Account> {

	private final AccountServiceImpl accountService;

	private final SystemSettingTypeDictionary systemSetting;

	private final RedisCacheManager redisCacheManager;

	private final UserServiceImpl userService;

	private final AuthTypeDictionary authTypeDictionary;

	@PostMapping("/resetPassword/{id}")
	@BindPermission(name = "重置密码", code = OperationCons.CODE_WRITE)
	public JsonResult<?> resetPassword(@PathVariable("id") Long id) throws Exception {
		Account entity = accountService.getEntity(id);
		entity.setAuthSecret(PasswordUtil.md5(systemSetting.getDefaultPassword() + entity.getSecretSalt()));
		accountService.updateEntity(entity);
		return JsonResult.OK("密码重置完成，新密码是【" + systemSetting.getDefaultPassword() + "】");
	}

	@GetMapping("/queryByUserId")
	@BindPermission(name = "根据用户ID获取账号", code = OperationCons.CODE_READ)
	public JsonResult queryByUserId(AccountDTO entity, Pagination pagination) throws Exception {
		QueryWrapper<AccountDTO> queryWrapper = super.buildQueryWrapperByQueryParams(entity);
		List<AccountVO> voList = accountService.getViewObjectList(queryWrapper, pagination, AccountVO.class);
		return JsonResult.OK(voList).bindPagination(pagination);
	}

	/**
	 * 根据资源id查询ViewObject
	 *
	 * @param id ID
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/{id}")
	@BindPermission(name = OperationCons.LABEL_DETAIL, code = OperationCons.CODE_READ)
	public JsonResult getViewObjectMapping(@PathVariable("id") Long id) throws Exception {
		return super.getViewObject(id, AccountVO.class);
	}

	/**
	 * 新建
	 *
	 * @param dto
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/create")
	@BindPermission(name = OperationCons.LABEL_CREATE, code = OperationCons.CODE_WRITE)
	public JsonResult createEntityMapping(@Valid @RequestBody AccountDTO dto) throws Exception {
		return super.createEntity(dto);
	}

	/**
	 * 更新
	 *
	 * @param dto
	 * @return JsonResult
	 * @throws Exception
	 */
	@PostMapping("/update/{id}")
	@BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
	public JsonResult updateEntityMapping(@PathVariable("id") Long id, @Valid @RequestBody AccountDTO dto) throws Exception {
		return super.updateEntity(id, dto);
	}

	/**
	 * 根据id删除资源对象
	 *
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/delete/{id}")
	@BindPermission(name = OperationCons.LABEL_DELETE, code = OperationCons.CODE_READ)
	public JsonResult deleteEntityMapping(@PathVariable("id") Long id) throws Exception {
		return super.deleteEntity(id);
	}

	@PostMapping("changPassword")
	@BindPermission(name = "修改密码", code = OperationCons.CODE_WRITE)
	public JsonResult<?> onChangPassword(@Valid @RequestBody ChangPasswordDTO dto) throws Exception {
		if (!dto.getPassword().equals(dto.getPasswordAgain())) {
			throw new BusinessException("密码不一致");
		}
		Account entity = this.getEntity(dto.getId());
		if (entity == null) {
			return JsonResult.FAIL_NOT_FOUND("账号不存在");
		}
		User user = userService.getEntity(entity.getUserId());
		String verifyKey;
		if (dto.getCodeType().equalsIgnoreCase("phone")) {
			verifyKey = Cons.PHONE_CODE_KEY + user.getPhone();
			String code = redisCacheManager.getCacheObject(verifyKey);
			if (!dto.getCode().equalsIgnoreCase(code)) {
				throw new BusinessException("短信验证码不正确");
			}
		} else {
			verifyKey = Cons.EMAIL_CODE_KEY + user.getEmail();
			String code = redisCacheManager.getCacheObject(verifyKey);
			if (!dto.getCode().equalsIgnoreCase(code)) {
				throw new BusinessException("验证码不正确");
			}
		}
		redisCacheManager.deleteObject(verifyKey);
		entity.setAuthSecret(PasswordUtil.md5(systemSetting.getDefaultPassword() + entity.getSecretSalt()));
		this.updateEntity(dto.getId(), entity);
		return JsonResult.OK();
	}

	@PostMapping("bindPhone")
	@BindPermission(name = "绑定手机号", code = OperationCons.CODE_WRITE)
	public JsonResult<?> bindPhone(@Valid @RequestBody BindPhoneDTO dto) throws Exception {
		User user = userService.getEntity(dto.getUserId());
		if (user == null) {
			return JsonResult.FAIL_NOT_FOUND("用户不存在");
		}
		String verifyKey = Cons.PHONE_CODE_KEY + user.getPhone();
		String code = redisCacheManager.getCacheObject(verifyKey);
		if (!dto.getCode().equalsIgnoreCase(code)) {
			throw new BusinessException("短信验证码不正确");
		}
		redisCacheManager.deleteObject(verifyKey);

		Account phone = new Account();
		phone.setUserId(user.getId());
		phone.setUserType(user.getUserType());
		phone.setAuthAccount(dto.getPhone());
		phone.setSecretSalt("icesoft-phone");
		phone.setAuthSecret(PasswordUtil.md5(systemSetting.getDefaultPassword() + phone.getSecretSalt()));
		phone.setAuthType(authTypeDictionary.getPhone());
		createEntity(phone);
		return JsonResult.OK();
	}

	@PostMapping("bindEmail")
	@BindPermission(name = "绑定邮箱", code = OperationCons.CODE_WRITE)
	public JsonResult<?> bindEmail(@Valid @RequestBody BindEmailDTO dto) throws Exception {
		User user = userService.getEntity(dto.getUserId());
		if (user == null) {
			return JsonResult.FAIL_NOT_FOUND("用户不存在");
		}
		String verifyKey = Cons.EMAIL_CODE_KEY + user.getEmail();
		String code = redisCacheManager.getCacheObject(verifyKey);
		if (!dto.getCode().equalsIgnoreCase(code)) {
			throw new BusinessException("验证码不正确");
		}
		redisCacheManager.deleteObject(verifyKey);

		Account email = new Account();
		email.setUserId(user.getId());
		email.setUserType(user.getUserType());
		email.setAuthAccount(dto.getEmail());
		email.setSecretSalt("icesoft-email");
		email.setAuthSecret(PasswordUtil.md5(systemSetting.getDefaultPassword() + email.getSecretSalt()));
		email.setAuthType(authTypeDictionary.getEmail());
		createEntity(email);
		return JsonResult.OK();
	}

}
